/**
 * @author Huy HCQ
 */
package pit.com.ordermobilesystem.http;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;




abstract public class BaseHttpApi implements HttpApi {
  protected static final Logger LOG = Logger.getLogger(BaseHttpApi.class.getCanonicalName());
  private boolean DEBUG=false;
  protected static final int TIMEOUT = 60;
  private static final String authKey = "thinktodo.net_";
  private final DefaultHttpClient mHttpClient;
  private final String boundary;
  private static final String LINE_FEED = "\r\n";  
  public BaseHttpApi() {
    mHttpClient = null;
	  boundary = "===" + System.currentTimeMillis() + "===";
  }

  public BaseHttpApi(DefaultHttpClient httpClient) {
    mHttpClient = httpClient;
	  boundary = "===" + System.currentTimeMillis() + "===";
  }

  public HttpURLConnection createHttpURLConnection(URL url,String method) throws IOException {
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setDoInput(true);
    conn.setUseCaches(false);
    conn.setConnectTimeout(TIMEOUT * 1000);
    conn.setRequestMethod(method);
    conn.setRequestProperty("Connection", "Keep-Alive");
    conn.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
    conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1");
    conn.setRequestProperty("Cookie","__atuvc=18%7C15%2C1%7C16%2C1%7C17%2C9%7C18%2C1%7C19; PHPSESSID=29k3psoq5ouv2f6a48rprqpor5; XDEBUG_SESSION=netbeans-xdebug");
    Encryption encry = new Encryption();
    conn.setRequestProperty("HASH", encry.encode(authKey + new Date().getTime()));
    return conn;
  }

  
	public String excuteHttpPost(String sUrl, String content) throws HttpApiException, IOException, JSONException{
		    URL url = new URL(sUrl);
		    StringBuilder response = new StringBuilder();
		    HttpURLConnection conn = createHttpURLConnection(url, "POST");
		    DataOutputStream dos = null;
		    BufferedReader in = null;
			try {
				conn.setDoOutput(true);
				dos = new DataOutputStream(conn.getOutputStream());
				byte[] request_body = content.getBytes();
				// send request string to server
				for (int i = 0; i < request_body.length; i++) {
					dos.writeByte(request_body[i]);
				}
				int statusCode = conn.getResponseCode();
				switch (statusCode) {
				case 200:
				case 204:
					in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
					String responseLine = "";
					while ((responseLine = in.readLine()) != null) {
						response.append(responseLine);
					}
					in.close();
					return response.toString();
				case 400:
					throw new HttpApiException(conn.getResponseMessage());
				case 401:
					throw new HttpApiException(conn.getResponseMessage());
				case 404:
					throw new HttpApiException(conn.getResponseMessage());
				case 500:
					throw new HttpApiException("Server is down. Try again later.");
				default:
					throw new HttpApiException("Error connecting to VinShowRoom: " + statusCode + ". Try again later.");
				}
			} finally {
				if (dos != null){
					dos.close();
				}				
				if (in != null){
					in.close();
				}				
				if (conn != null){
					conn.disconnect();
				}				
			}	

		}  
  
	public String excuteHttpGet(String sUrl) throws HttpApiException, IOException, JSONException {
		URL url = new URL(sUrl);
	    StringBuilder response = new StringBuilder();
	    HttpURLConnection conn = createHttpURLConnection(url, "GET");
	    DataOutputStream dos = null;
	    BufferedReader in = null;
		try {
			int statusCode = conn.getResponseCode();
			switch (statusCode) {
			case 200:
			case 204:
				in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
				String responseLine = "";
				while ((responseLine = in.readLine()) != null) {
					response.append(responseLine);
				}
				in.close();
				return response.toString();
			case 400:
				throw new HttpApiException(conn.getResponseMessage());
			case 401:
				throw new HttpApiException(conn.getResponseMessage());
			case 404:
				throw new HttpApiException(conn.getResponseMessage());
			case 500:
				throw new HttpApiException("Server is down. Try again later.");
			default:
				throw new HttpApiException("Error connecting to VinShowRoom: " + statusCode+ ". Try again later.");
			}
		} finally {
			if (dos != null){
				dos.close();
			}				
			if (in != null){
				in.close();
			}				
			if (conn != null){
				conn.disconnect();
			}				
		}
	}  
	
	  public final static byte[] getByteFromFile(String fileName)
	  {
	    try { 
	      FileInputStream fin=new FileInputStream(fileName);
	      byte readBuf[] = new byte[512*1024];
	      ByteArrayOutputStream bout = new ByteArrayOutputStream();
	      
	        int readCnt = fin.read(readBuf);
	        while (0 < readCnt) {
	          bout.write(readBuf, 0, readCnt);
	          readCnt = fin.read(readBuf);
	        }
	        
	        fin.close();
	        
	        return bout.toByteArray();

	    }
	    catch (Exception e) {
	 
	      return new byte[0];
	    }
	  }
	  
  
	  public String executeHttpRequestMultipart(String sUrl,String data,String[] path_images) throws IOException {
			    Exception exception = null;
			    URL url = new URL(sUrl);
			    StringBuilder response = new StringBuilder();
			    HttpURLConnection conn = createHttpURLConnection(url, "GET");
			    DataOutputStream dos = null;
			    BufferedReader in = null;
			    try {
			      conn.setRequestMethod("POST");
			      conn.setDoOutput(true);
			      conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);      
			      dos = new DataOutputStream(conn.getOutputStream());
			      PrintWriter writer = new PrintWriter(new OutputStreamWriter(dos, "UTF-8"), true);
			      writer.append("--" + boundary).append(LINE_FEED);
			      writer.append("Content-Disposition: form-data; name=\"" + "data" + "\"")
			              .append(LINE_FEED);
			      writer.append("Content-Type: text/plain; charset=" + "UTF-8").append(
			              LINE_FEED);
			      writer.append(LINE_FEED);
			      writer.append(data).append(LINE_FEED);
			      writer.flush();

			      for(int i=0;i<path_images.length;i++){
				      File file = new File(path_images[i]);
				      FileInputStream fin=new FileInputStream(file);
				      String fileName=file.getName();
				      writer.append("--" + boundary).append(LINE_FEED);
				      writer.append(
				              "Content-Disposition: form-data; name=\"" +  "file" 
				                      + "\"; filename=\"" + fileName + "\"")
				              .append(LINE_FEED);
				      writer.append(
				              "Content-Type: "
				                      + HttpURLConnection.guessContentTypeFromName(fileName))
				              .append(LINE_FEED);
				      writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
				      writer.append(LINE_FEED);
				      writer.flush();
				      dos.write(getByteFromFile(path_images[i]));
				      writer.append(LINE_FEED);
				      writer.flush();  
			      }
			      writer.append(LINE_FEED).flush();
			      writer.append("--" + boundary + "--").append(LINE_FEED);
			      writer.close();     
			      int statusCode = conn.getResponseCode();
			      switch (statusCode) {
			      case 200:
			        
			      case 204:       
			        in = new BufferedReader(new InputStreamReader(
			            conn.getInputStream(), "UTF-8"));
			        String responseLine = "";
			        while ((responseLine = in.readLine()) != null) {
			          response.append(responseLine);
			        }
			        in.close();
			        return response.toString();
			      case 400:
			        if (DEBUG)
			          LOG.log(Level.FINE, "HTTP Code: 400");
			        throw new HttpApiException(conn.getResponseMessage());
			      case 401:
			        // response.getEntity().consumeContent();
			        if (DEBUG)
			          LOG.log(Level.FINE, "HTTP Code: 401");
			        throw new HttpApiException(conn.getResponseMessage());
			      case 404:
			        if (DEBUG)
			          LOG.log(Level.FINE, "HTTP Code: 404");
			        throw new HttpApiException(conn.getResponseMessage());
			      case 500:
			        if (DEBUG)
			          LOG.log(Level.FINE, "HTTP Code: 500");
			        throw new HttpApiException(
			            "MobiPlace is down. Try again later.");
			      default:
			        if (DEBUG)
			          LOG.log(Level.FINE, "Error connecting to server: "
			              + Integer.toString(statusCode));
			        throw new HttpApiException("Error connecting to server: "
			            + statusCode + ". Try again later.");
			      }
			      // obtain DataInputStream for receiving server response
			    } catch (Exception e) {
			      exception = e;
			    } finally {
			      if (dos != null)
			        dos.close();
			      if (in != null)
			        in.close();
			      if (conn != null)
			        conn.disconnect();
			    }
			    return null;
			  } 
	  
		private static final HttpParams createHttpParams() {
			final HttpParams params = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(params, TIMEOUT * 1000);
			HttpConnectionParams.setSoTimeout(params, TIMEOUT * 1000);

			return params;
		}	  
	  
		public String excuteHttpUploadFile(String sUrl,  String filePath) throws Exception {
			String mResponse = null;
			String strException=null;
			HttpClient httpClient = new DefaultHttpClient(createHttpParams());
			HttpPost httpPost = new HttpPost(sUrl);
			httpPost.addHeader("Accept","application/json");
			httpPost.addHeader("Connection", "Keep-Alive");
			httpPost.addHeader("Content-Type", "text/plain; charset=utf-8");
			httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1");
			httpPost.addHeader("Cookie","__atuvc=18%7C15%2C1%7C16%2C1%7C17%2C9%7C18%2C1%7C19; PHPSESSID=29k3psoq5ouv2f6a48rprqpor5; XDEBUG_SESSION=netbeans-xdebug");
			File file = new File(filePath);		
			FileEntity entity = new FileEntity(file, "UTF-8");
			
			httpPost.setEntity(entity);		
			HttpResponse response;
			try {
				response = httpClient.execute(httpPost);
				BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
				mResponse = reader.readLine();
			} catch (ClientProtocolException e) {
				strException = e.getMessage();
			} catch (IOException e) {
				strException = e.getMessage();
			}
			if(strException != null){
				throw new HttpApiException(strException);
			}
			return mResponse;	
		}	  
}
